<?php
class JobHandler {
	public static function getDefaultUrgencies() {
		return array(
			msg('High', true),
			msg('Normal', true),
			msg('Low', true),
		);
	}

	public static function getDefaultStatuses() {
		return array(
			array(
				'caption' => msg('Not started', true),
				'visible' => 1
			),
			array(
				'caption' => msg('In planning', true),
				'visible' => 1
			),
			array(
				'caption' => msg('In progress', true),
				'visible' => 1
			),
			array(
				'caption' => msg('Done', true),
				'visible' => 0
			),
			array(
				'caption' => msg('Cancelled', true),
				'visible' => 0
			),
			array(
				'caption' => msg('Waiting', true),
				'visible' => 1
			),
			array(
				'caption' => msg('Continuous', true),
				'visible' => 1
			),
			array(
				'caption' => msg('Failed', true),
				'visible' => 0
			),
			array(
				'caption' => msg('Sent elsewhere', true),
				'visible' => 0
			)
		);
	}
	
	public static function publicProjectsExist() {
		try {
			if (DATABASE_OK !== true) {
				return false;
			}

			if (isset($GLOBALS['job']['public_projects_exist'])) {
				return $GLOBALS['job']['public_projects_exist'];
			}

			$oQuery = DataHandler::query("
				SELECT COUNT(*)
				FROM jobconfig
				WHERE varname = 'bPublic'
				AND varvalue = '1'
			");

			list($iCount) = $oQuery->fetch(PDO::FETCH_NUM);

			$GLOBALS['job']['public_projects_exist'] = ($iCount > 0);

			return $GLOBALS['job']['public_projects_exist'];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function getLog($iJob, $iFromTime, $iToTime) {
		try {
			$oQuery = DataHandler::query("
				SELECT
					l.mission_id,
					l.timing,
					l.actiontype,
					l.stat_todo,
					l.stat_group_id,
					l.stat_urgency_id,
					l.stat_finishtime,
					l.stat_status,
					l.stat_users
				FROM
					missionlog l,
					missions m
				WHERE m.id = l.mission_id
				AND m.job_id = ?
				AND l.timing >= ?
				AND l.timing <= ?
				ORDER BY
					l.timing,
					l.stat_group_id
			", $iJob, $iFromTime, $iToTime);
			
			$oLog = array();
			while ($oRow = $oQuery->fetch(PDO::FETCH_ASSOC)) {
				$oEntity = array(
					'mission_id' => $oRow['mission_id'],
					'timing' => $oRow['timing'],
					'actiontype' => $oRow['actiontype'],
					'todo' => $oRow['stat_todo'],
					'group_id' => $oRow['stat_group_id'],
					'urgency_id' => $oRow['stat_urgency_id'],
					'finishtime' => $oRow['stat_finishtime'],
					'status' => $oRow['stat_status'],
					'users' => $oRow['stat_users'],
				);
				array_push($oLog, $oEntity);
			}
			return $oLog;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getCurrentJob() {
		return JobHandler::getJob($_SESSION['iJobID']);
	}
	
	public static function getJob($iJob) {
		$oJobs = JobHandler::getJobs();
		return $oJobs[$iJob];
	}
	
	public static function getConfigTypes() {
		$oJobConfigTypes = array(
			'bPublic' => array(
				'type' => 'bool',
				'caption' => msg('Visible in project center')
			),
			'bAllowNogroupMissions' => array(
				'type' => 'bool',
				'caption' => msg('Allow tasks outside taskgroups'),
				'default' => 1
			),
			'bAllowUserlessMissions' => array(
				'type' => 'bool',
				'caption' => msg('Allow tasks without user')
			),
			'bUseWork' => array(
				'type' => 'bool',
				'caption' => msg('Use timekeeping')
			),
			'bShowReminder' => array(
				'type' => 'bool',
				'caption' => msg('Show reminder button')
			),
		);
		return $oJobConfigTypes;
	}
	
	public static function getJobQueryString($sField = 'job_id') {
		try {
			if (is_string(@$GLOBALS['job']['querystring'])) {
				return $GLOBALS['job']['querystring'];
			}

			$oUserQuery = DataHandler::query("
				SELECT job_id
				FROM job_access_users
				WHERE user_id = ?
				AND element = 'job'
				AND access = 'read'
			", $_SESSION['rid']);

			$oUsergroupQuery = DataHandler::query("
				SELECT b.job_id
				FROM
					users_groups a,
					job_access_usergroups b
				WHERE a.usergroup_id = b.usergroup_id
				AND a.user_id = ?
				AND b.element = 'job'
				AND b.access = 'read'
			", $_SESSION['rid']);

			$iJobs = array();
			while (list($iID) = $oUserQuery->fetch(PDO::FETCH_NUM)) {
				array_push($iJobs, $iID);
			}
			while (list($iID) = $oUsergroupQuery->fetch(PDO::FETCH_NUM)) {
				array_push($iJobs, $iID);
			}

			$GLOBALS['job']['querystring'] = array_unique($iJobs);

			return $GLOBALS['job']['querystring'];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	// Gets the counts of missions by status. Caches all accessible jobs.
	public static function getJobStatus($iJob) {
		try {
			if (@is_array($GLOBALS['job']['jobstatus'][$iJob])) {
				return $GLOBALS['job']['jobstatus'][$iJob];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					job_id,
					status
				FROM missions
				WHERE job_id IN (".implode(',', JobHandler::getJobQueryString()).")
			");
			
			$iStatusArray = array();
			while ($oRow = $oQuery->fetch(PDO::FETCH_ASSOC)) {
				$iStatusJob = $oRow['job_id'];
				$iStatus = $oRow['status'];
				
				if (!is_int(@$iStatusArray[$iStatusJob][$iStatus])) {
					$iStatusArray[$iStatusJob][$iStatus] = 0;
				}
				
				$iStatusArray[$iStatusJob][$iStatus]++;
			}
			
			if (!is_array(@$iStatusArray[$iJob])) {
				$iStatusArray[$iJob] = array();
			}
			
			$GLOBALS['job']['jobstatus'] = $iStatusArray;
			
			return $GLOBALS['job']['jobstatus'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function setOwner($iJob, $iUser) {
		try {
			// -1 = Unknown SQL error.
			// -2 = Cannot take ownership; owner already defined.
			// -3 = Cannot give jobs you don't own yourself.
			$oJob = JobHandler::getJob($iJob);
			
			if ($oJob->iOwner) {
				if ($oJob->iOwner == $_SESSION['rid']) {
					$oAccess = array(
						'job-read' => 1,
						'job-write' => 1,
						'mission-read' => 1,
						'mission-write' => 1,
						'file-read' => 1,
						'file-write' => 1
					);
					JobHandler::setUserAccess($iJob, $iUser, $oAccess);
				}
				else {
					throw new MiJobException('Cannot give jobs you don\'t own yourself.');
				}
				
				if ($iUser == $_SESSION['rid']) {
					throw new MiJobException('You already own this project');
				}
			}
			
			DataHandler::query("
				UPDATE jobs
				SET owner = ?
				WHERE id = ?
			", $iUser, $iJob);
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function setDescription($iJob, $sDescription) {
		DataHandler::query("
			UPDATE jobs
			SET description = ?
			WHERE id = ?
		", $sDescription, $iJob);
		
		return true;
	}
	
	public static function getUsersWithAccess($sElement, $sAccess, $iJob = 0) {
		$iJob = ($iJob ? $iJob : $_SESSION['iJobID']);
		$oUserAccess = JobHandler::getUserAccess($iJob);
		$iAccessUsers = array();
		foreach ($oUserAccess as $iUser => $oAccessMatrix) {
			if ($oAccessMatrix[$sElement][$sAccess]) {
				array_push($iAccessUsers, $iUser);
			}
		}
		return $iAccessUsers;
	}
	
	public static function canDo($sElement, $sNeedAccess, $iJob = 0, $iUser = 0) {
		$iJob = ($iJob ? $iJob : $_SESSION['iJobID']);
		$iUser = ($iUser ? $iUser : $_SESSION['rid']);
		if (JobHandler::canUserDo($sElement, $sNeedAccess, $iUser, $iJob)) {
			return true;
		}
		return false;
	}
	
	public static function canUserDo($sElement, $sNeedAccess, $iUser = 0, $iJob = 0) {
		$iJob = ($iJob ? $iJob : $_SESSION['iJobID']);
		$iUser = ($iUser ? $iUser : $_SESSION['rid']);
		$oUserAccess = JobHandler::getUserAccess($iJob);
		return $oUserAccess[$iUser][$sElement][$sNeedAccess];
	}
	
	public static function getUsergroupAccess($iJob) {
		try {
			if (is_array($GLOBALS['job']['usergroupaccess'][$iJob])) {
				return $GLOBALS['job']['usergroupaccess'][$iJob];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					usergroup_id,
					element,
					access
				FROM job_access_usergroups
				WHERE job_id = ?
			", $iJob);
			
			$oUsergroupAccess = array();
			while (list($iUsergroup, $sElement, $sAccess) = $oQuery->fetch(PDO::FETCH_NUM)) {
				if (!is_array($oUsergroupAccess[$iUsergroup])) {
					$oUsergroupAccess[$iUsergroup] = array(
						'issue' => array(
							'read' => false,
							'write' => false
						),
						'job' => array(
							'read' => false,
							'write' => false
						),
						'mission' => array(
							'read' => false,
							'write' => false
						),
						'file' => array(
							'read' => false,
							'write' => false
						)
					);
				}
				$oUsergroupAccess[$iUsergroup][$sElement][$sAccess] = true;
			}
			
			$GLOBALS['job']['usergroupaccess'][$iJob] = $oUsergroupAccess;
			
			return $GLOBALS['job']['usergroupaccess'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	// Gets a list of all users that have access to the job, whether through user or usergroup.
	// When $bSkipFromGroups is true, only get access by user, not usergroup.
	// No cache when $bSkipFromGroups is true.
	public static function getUserAccess($iJob, $bSkipFromGroups = false) {
		try {
			if (@is_array($GLOBALS['job']['useraccess'][$iJob]) && !$bSkipFromGroups) {
				return $GLOBALS['job']['useraccess'][$iJob];
			}

			$oQuery = DataHandler::query("
				SELECT DISTINCT
					user_id,
					element,
					access
				FROM job_access_users
				WHERE job_id = ?
			", $iJob);

			$oUserAccess = array();
			while (list($iUser, $sElement, $sAccess) = $oQuery->fetch(PDO::FETCH_NUM)) {
				$oUserAccess[$iUser][$sElement][$sAccess] = true;
			}

			if (!$bSkipFromGroups) {
				$oGroupQuery = DataHandler::query("
					SELECT DISTINCT
						a.user_id,
						b.element,
						b.access
					FROM
						users_groups a,
						job_access_usergroups b
					WHERE 
						a.usergroup_id = b.usergroup_id
						AND b.job_id = ?
				", $iJob);

				while (list($iUser, $sElement, $sAccess) = $oGroupQuery->fetch(PDO::FETCH_NUM)) {
					$oUserAccess[$iUser][$sElement][$sAccess] = true;
				}
			}

			if ($bSkipFromGroups) {
				return $oUserAccess;
			}
			else {
				$GLOBALS['job']['useraccess'][$iJob] = $oUserAccess;
				return $GLOBALS['job']['useraccess'][$iJob];
			}

			return $oUserAccess;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function setUsergroupAccess($iJob, $iUsergroup, $oAccess) {
		try {
			if (!is_array($oAccess)) {
				$oAccess = array();
			}
			
			if (!$iUsergroup) {
				throw new MiJobException('Missing user ID');
			}
			
			DataHandler::query("
				DELETE FROM job_access_usergroups
				WHERE job_id = ?
				AND usergroup_id = ?
			", $iJob, $iUsergroup);
			
			foreach ($oAccess as $sKey => $sDummy) {
				list($sElement, $sAccess) = split('-', $sKey);
				DataHandler::query("
					INSERT INTO job_access_usergroups (
						job_id,
						usergroup_id,
						element,
						access
					) VALUES (
						?,
						?,
						?,
						?
					)
				", $iJob, $iUsergroup, $sElement, $sAccess);
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function setUserAccess($iJob, $iUser, $oAccess) {
		try {
			// -1 = Unknown SQL error.
			// -2 = Can't change your own rights.
			// -3 = Missing user ID.
			// -4 = Can't change job owner's rights.
			if (!is_array($oAccess)) {
				$oAccess = array();
			}
			
			$oJob = JobHandler::getJob($iJob);
			if ($oJob->iOwner == $iUser) {
				throw new MiJobAccessException('Can\'t change job owner\'s rights.');
			}
			
			if (!$iUser) {
				throw new MiJobException('Missing user ID');
			}
			
			else if ($iUser == $_SESSION['rid']) {
				throw new MiJobAccessException('Can\'t change your own rights');
			}
			
			DataHandler::query("
				DELETE FROM job_access_users
				WHERE job_id = ?
				AND user_id = ?
			", $iJob, $iUser);
			
			foreach ($oAccess as $sKey => $sDummy) {
				list($sElement, $sAccess) = split('-', $sKey);
				DataHandler::query("
					INSERT INTO job_access_users (
						job_id,
						user_id,
						element,
						access
					) VALUES (
						?,
						?,
						?,
						?
					)
				", $iJob, $iUser, $sElement, $sAccess);
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeGroup($iJob, $iJobgroup)
	{
		try {
			$oCheckQuery = DataHandler::query("
				SELECT id
				FROM jobgroups_jobs
				WHERE job_id = ?
				AND user_id = ?
			", $iJob, $_SESSION['rid']);

			if ($oCheckQuery->rowCount() > 0) {
				DataHandler::query("
					UPDATE jobgroups_jobs
					SET jobgroup_id = ?
					WHERE job_id = ?
					AND user_id = ?
				", $iJobgroup, $iJob, $_SESSION['rid']);
			}
			else {
				DataHandler::query("
					INSERT INTO jobgroups_jobs (
						job_id,
						jobgroup_id,
						user_id
					) VALUES (
						?,
						?,
						?
					)
				", $iJob, $iJobgroup, $_SESSION['rid']);
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getMissionTodos($iJob)
	{
		try {
			if (is_array(@$GLOBALS['job']['missiontodos'][$iJob]))
			{
				return $GLOBALS['job']['missiontodos'][$iJob];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					id,
					todo
				FROM missions
				WHERE job_id = ?
			", $iJob);
			
			$sMissionTodos = array();
			while (list($iID, $sMissionTodo) = $oQuery->fetch(PDO::FETCH_NUM)) {
				$sMissionTodos[$iID] = $sMissionTodo;
			}
			
			$GLOBALS['job']['missiontodos'][$iJob] = $sMissionTodos;
			
			return $GLOBALS['job']['missiontodos'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function setConfig($iJob, $sVarName, $mVarValue)
	{
		try {
			$oCheckQuery = DataHandler::query("
				SELECT varvalue
				FROM jobconfig
				WHERE job_id = ?
				AND varname = ?
			", $iJob, $sVarName);
			
			if ($oCheckQuery->rowCount() == 0) {
				DataHandler::query("
					INSERT INTO jobconfig (
						job_id,
						varname,
						varvalue
					) VALUES (
						?,
						?,
						?
					)
				", $iJob, $sVarName, $mVarValue);
			}
			else {
				DataHandler::query("
					UPDATE jobconfig
					SET
						varvalue = ?
					WHERE job_id = ?
					AND varname = ?
				", $mVarValue, $iJob, $sVarName);
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getConfig($iJob)
	{
		try {
			if (@is_array($GLOBALS['jobconfig'][$iJob]))
			{
				return $GLOBALS['jobconfig'][$iJob];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					varname,
					varvalue
				FROM jobconfig
				WHERE job_id = ?
			", $iJob);
			
			$GLOBALS['jobconfig'][$iJob] = array();
			while (list($sVarname, $sVarvalue) = $oQuery->fetch(PDO::FETCH_NUM))
			{
				$GLOBALS['jobconfig'][$iJob][$sVarname] = $sVarvalue;
			}
			
			return $GLOBALS['jobconfig'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function delMissiongroup($iJob, $iMissiongroupID)
	{
		try {
			DataHandler::beginTransaction();
			
			DataHandler::query("
				DELETE FROM missiongroups
				WHERE id = ?
			", $iMissiongroupID);
			
			DataHandler::query("
				UPDATE missions
				SET group_id = '0'
				WHERE group_id = ?
			", $iMissiongroupID);
			
			DataHandler::commit();
			
			if (is_array($GLOBALS['jobs'][$iJob]->sMissiongroups))
			{
				unset($GLOBALS['jobs'][$iJob]->sMissiongroups[$iMissiongroupID]);
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeMissiongroup($iJob, $iMissiongroupID, $sName)
	{
		try {
			if (!$sName) {
				throw new MiJobException('Mission group must have a name');
			}
			
			$oCheckQuery = DataHandler::query("
				SELECT id
				FROM missiongroups
				WHERE job_id = ?
				AND name = ?
				AND id != ?
			", $iJob, $sName, $iMissiongroupID);
			
			if ($oCheckQuery->rowCount() > 0) {
				throw new MiJobException('Mission group already exists');
			}
			
			DataHandler::query("
				UPDATE missiongroups
				SET name = ?
				WHERE id = ?
			", $sName, $iMissiongroupID);
			
			if (is_array($GLOBALS['jobs'][$iJob]->sMissiongroups))
			{
				$GLOBALS['jobs'][$iJob]->sMissiongroups[$iMissiongroupID] = $sName;
			}
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function addMissiongroup($iJob, $sName)
	{
		try {
			if (!$sName) {
				throw new MiJobException('Missio group must have name');
			}
			
			$oCheckQuery = DataHandler::query("
				SELECT id
				FROM missiongroups
				WHERE job_id = ?
				AND name = ?
			", $iJob, $sName);
			
			if ($oCheckQuery->rowCount() > 0) {
				throw new MiJobException('Mission group already exists');
			}
			
			DataHandler::query("
				INSERT INTO missiongroups (
					job_id,
					name
				) VALUES (
					?,
					?
				)
			", $iJob, $sName);
			
			$iNewID = DataHandler::lastInsertId();
			
			if (is_array($GLOBALS['jobs'][$iJob]->sMissiongroups))
			{
				$GLOBALS['jobs'][$iJob]->sMissiongroups[$iNewID] = $sName;
			}
			
			return $iNewID;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getMissiongroups($iJob)
	{
		try {
			if (is_array(@$GLOBALS['jobs'][$iJob]->sMissiongroups)) {
				return $GLOBALS['jobs'][$iJob]->sMissiongroups;
			}

			$oQuery = DataHandler::query("
				SELECT
					id,
					name
				FROM missiongroups
				WHERE job_id = ?
				ORDER BY name
			", $iJob);
			
			$sMissiongroups = array();
			while (list($iID, $sName) = $oQuery->fetch(PDO::FETCH_NUM)) {
				$sMissiongroups[$iID] = $sName;
			}
			
			if (@$GLOBALS['jobs'][$iJob]) {
				$GLOBALS['jobs'][$iJob]->sMissiongroups = $sMissiongroups;
			}
			
			return $sMissiongroups;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function changeUrgencies($iJob, $sUrgencies)
	{
		try {
			DataHandler::query("
				UPDATE jobs
				SET urgencies = ?
				WHERE id = ?
			", $sUrgencies, $iJob);
			
			$GLOBALS['jobs'][$iJob]->sUrgencies = split('\|', trim($sUrgencies, '|'));
			
			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function delJob($iJob)
	{
		try {
			DataHandler::beginTransaction();
			
			DataHandler::query("
				DELETE FROM jobs
				WHERE id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM jobgroups_jobs
				WHERE job_id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM job_access_users
				WHERE job_id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM job_access_usergroups
				WHERE job_id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM jobconfig
				WHERE job_id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM missiongroups
				WHERE job_id = ?
			", $iJob);

			DataHandler::query("
				DELETE FROM notes
				WHERE job_id = ?
			", $iJob);

			$oMissionMissionQuery = DataHandler::query("
				SELECT id
				FROM missions
				WHERE job_id = ?
			", $iJob);
			while (list($iMissionID) = $oMissionMissionQuery->fetch(PDO::FETCH_NUM))
			{
				DataHandler::query("
					DELETE FROM missionlog
					WHERE mission_id = ?
				", $iMissionID);

				DataHandler::query("
					DELETE FROM work
					WHERE mission_id = ?
				", $iMissionID);
			}

			DataHandler::query("
				DELETE FROM missions
				WHERE job_id = ?
			", $iJob);
			
			DataHandler::commit();
			
			unset($GLOBALS['jobs'][$iJob]);
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeJob($iJob, $sName) {
		try {
			if (!$sName) {
				ErrorHandler::formError('sName', 'Project must have a name');
			}

			if (ErrorHandler::hasFormErrors()) {
				return false;
			}
			
			DataHandler::query("
				UPDATE jobs
				SET name = '$sName'
				WHERE id = '$iJob'
			", $sName, $iJob);
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function addJob($sName) {
		try {
			$oJobConfigTypes = JobHandler::getConfigTypes();
			
			if (!$sName) {
				ErrorHandler::formError('sName', 'Project must have a name');
			}

			if (ErrorHandler::hasFormErrors()) {
				return false;
			}
			
			DataHandler::query("
				INSERT INTO jobs (
					name,
					start,
					urgencies,
					owner
				) VALUES (
					?,
					?,
					?,
					?
				)
			", $sName, thisSecond(), implode('|', JobHandler::getDefaultUrgencies()), $_SESSION['rid']);
			
			$iNewID = DataHandler::lastInsertId();
			
			foreach ($oJobConfigTypes as $sVarname => $oThisConfigType)
			{
				if (@$oThisConfigType['default'])
				{
					DataHandler::query("
						INSERT INTO jobconfig (
							job_id,
							varname,
							varvalue
						) VALUES (
							?,
							?,
							?
						)
					", $iNewID, $sVarname, $oThisConfigType['default']);
				}
			}
			
			$sElements = array(
				'issue',
				'job',
				'mission',
				'file'
			);
			
			foreach ($sElements as $sThisElement) {
				DataHandler::query("
					INSERT INTO job_access_users (
						job_id,
						user_id,
						element,
						access
					) VALUES (
						?,
						?,
						?,
						?
					)
				", $iNewID, $_SESSION['rid'], $sThisElement, 'read');
				
				DataHandler::query("
					INSERT INTO job_access_users (
						job_id,
						user_id,
						element,
						access
					) VALUES (
						?,
						?,
						?,
						?
					)
				", $iNewID, $_SESSION['rid'], $sThisElement, 'write');
			}

			return $iNewID;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function getPublicJobs() {
		try {
			if (is_array(@$GLOBALS['publicjobs'])) {
				return $GLOBALS['publicjobs'];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					j.id,
					j.name,
					j.start,
					j.urgencies,
					j.updated,
					j.owner,
					j.description,
					j.issue_count
				FROM
					jobs j,
					jobconfig c
				WHERE c.job_id = j.id
				AND c.varname = 'bPublic'
				AND c.varvalue = '1'
				ORDER BY j.name
			");
			
			$oPublicJobs = array();
			while (list($iID, $sName, $iStart, $sUrgencies, $iUpdated, $iOwner, $sDescription, $iIssueCount) = $oQuery->fetch(PDO::FETCH_NUM)) {
				$sUrgencyArray = split('\|', trim($sUrgencies, '|'));
				$oPublicJobs[$iID] = new Job($iID, $sName, $iStart, $sUrgencyArray, $iUpdated, $iOwner, $sDescription, $iIssueCount);
			}

			$GLOBALS['publicjobs'] = $oPublicJobs;

			return $GLOBALS['publicjobs'];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getJobs(/* $iUser = 0 // To kill? */)
	{
		try {
			if (@is_array($GLOBALS['jobs'])) {
				return $GLOBALS['jobs'];
			}
			
			$iUser = @$_SESSION['rid'];
			/* To kill? 2011-12-26
			$iUser = ($iUser ? $iUser : (int)@$_SESSION['rid']);
			if (!$iUser) {
				return array();
			}
			*/
			
			$oQuery = DataHandler::query("
				SELECT
					j.id,
					j.name,
					j.start,
					j.urgencies,
					j.updated,
					j.owner,
					j.description,
					j.issue_count,
					COALESCE(jj.jobgroup_id, 0) AS jobgroup_id
				FROM
					jobs AS j
					INNER JOIN job_access_users AS jau ON jau.job_id = j.id
					LEFT OUTER JOIN jobgroups_jobs AS jj ON (
						jj.job_id = j.id
						AND jj.user_id = ?
					)
				WHERE
					jau.user_id = ?
					AND jau.element = 'job'
					AND jau.access = 'read'
				ORDER BY
					j.name
			", $iUser, $iUser);
			
			$oJobs = array();
			while (list($iID, $sName, $iStart, $sUrgencies, $iUpdated, $iOwner, $sDescription, $iIssueCount, $iJobgroup) = $oQuery->fetch(PDO::FETCH_NUM))
			{
				$sUrgencyArray = split('\|', trim($sUrgencies, '|'));
				$oJobs[$iID] = new Job($iID, $sName, $iStart, $sUrgencyArray, $iUpdated, $iOwner, $sDescription, $iIssueCount, $iJobgroup);
			}
			
			$oUsergroups = UserHandler::getUsergroups($iUser);
			if (count($oUsergroups) > 0) {
				$bFirst = true;
				$sExtraQuery = "";
				foreach ($oUsergroups as $iID => $oThisUsergroup) {
					$sExtraQuery .= ($bFirst ? "" : "OR");
					$sExtraQuery .= " jaug.usergroup_id = '$iID'\n";
					$bFirst = false;
				}
				
				$oQuery = DataHandler::query("
					SELECT
						j.id,
						j.name,
						j.start,
						j.urgencies,
						j.owner,
						j.description,
						j.issue_count,
						COALESCE(jj.jobgroup_id, 0) AS jobgroup_id
					FROM
						jobs AS j
						INNER JOIN job_access_usergroups AS jaug ON jaug.job_id = j.id
						LEFT OUTER JOIN jobgroups_jobs AS jj ON (
							jj.job_id = j.id
							AND jj.user_id = ?
						)
					WHERE
						jaug.element = 'job'
						AND jaug.access = 'read'
						AND (
							$sExtraQuery
						)
					ORDER BY
						j.name
				", $iUser);
				
				while (list($iID, $sName, $iStart, $sUrgencies, $iUpdated, $iOwner, $sDescription, $iIssueCount, $iJobgroup) = $oQuery->fetch(PDO::FETCH_NUM))
				{
					$sUrgencyArray = split('\|', trim($sUrgencies, '|'));
					if (!$oJobs[$iID]) {
						$oJobs[$iID] = new Job($iID, $sName, $iStart, $sUrgencyArray, $iUpdated, $iOwner, $sDescription, $iIssueCount, $iJobgroup);
					}
				}
			}
			
			$GLOBALS['jobs'] = $oJobs;
			
			return $GLOBALS['jobs'];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getFiles($iJob)
	{
		try {
			if (@is_array($GLOBALS['job']['files'][$iJob]))
			{
				return $GLOBALS['job']['files'][$iJob];
			}
			
			$oQuery = DataHandler::query("
				SELECT
					id,
					filename,
					description
				FROM files
				WHERE job_id = ?
			", $iJob);
			
			$GLOBALS['job']['files'][$iJob] = array();
			while ($oRow = $oQuery->fetch(PDO::FETCH_ASSOC)) {
				$oFile = array();
				$oFile['iID'] = $oRow['id'];
				$oFile['sFilename'] = $oRow['filename'];
				$oFile['sDescription'] = $oRow['description'];
				$GLOBALS['job']['files'][$iJob][$oRow['id']] = (object)$oFile;
			}
			return $GLOBALS['job']['files'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function addFile($iJob, $oFile, $sDescription)
	{
		try {
			// -1 = Couldn't create job folder.
			// -2 = Failed writing the file to disk.
			// -3 = Unknown SQL error.
			// -4 = FILES_DIR must be writable.
			if (!is_writable(FILES_DIR)) {
				throw new MiJobException('FILES_DIR must be writable');
			}
			
			DataHandler::beginTransaction();
			
			DataHandler::query("
				DELETE FROM files
				WHERE job_id = ?
				AND filename = ?
			", $iJob, $oFile['name']);
			
			if (!is_dir(FILES_DIR.'/'.$iJob)) {
				if (!@mkdir(FILES_DIR.'/'.$iJob)) {
					throw new MiJobException('Couldn\'t create job folder');
				}
			}
			
			if (!move_uploaded_file($oFile['tmp_name'], FILES_DIR.'/'.$iJob.'/'.$oFile['name'])) {
				throw new MiJobException('Failed writing the file to disk');
			}

			DataHandler::query("
				INSERT INTO files (
					filename,
					description,
					job_id
				) VALUES (
					?,
					?,
					?
				)
			", $oFile['name'], $sDescription, $iJob);
			
			DataHandler::commit();
			
			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function changeFile($iJob, $iFile, $sDescription) {
		try {
			// -1 = Unknown SQL error.
			DataHandler::query("
				UPDATE files
				SET description = ?
				WHERE id = ?
				AND job_id = ?
			", $sDescription, $iFile, $iJob);

			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function delFile($iJob, $iFile)
	{
		try {
			// -1 = File doesn't exist.
			// -2 = Failed to delete file.
			$oNameQuery = DataHandler::query("
				SELECT filename
				FROM files
				WHERE id = ?
				AND job_id = ?
			", $iFile, $iJob);

			list($sFilename) = $oNameQuery->fetch(PDO::FETCH_NUM);

			DataHandler::query("
				DELETE FROM files
				WHERE job_id = ?
				AND id = ?
			", $iJob, $iFile);

			$oMissionQuery = DataHandler::query("
				SELECT mission_id
				FROM missions_files
				WHERE file_id = ?
			", $iFile);
			
			$iCleanMissions = array();
			while (list($iMission) = $oMissionQuery->fetch(PDO::FETCH_NUM)) {
				array_push($iCleanMissions, $iMission);
			}
			
			DataHandler::query("
				DELETE FROM missions_files
				WHERE file_id = ?
			", $iFile);
			
			foreach ($iCleanMissions as $iThisMission) {
				MissionHandler::fixFileCount($iThisMission);
			}

			if (!is_file(FILES_DIR.'/'.$iJob.'/'.$sFilename)) {
				throw new MiJobException('File doesn\'t exist');
			}

			if (!unlink(FILES_DIR.'/'.$iJob.'/'.$sFilename)) {
				throw new MiJobException('Failed to delete file');
			}

			return true;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function downloadFile($iJob, $sFile) {
		if (!is_file(FILES_DIR.'/'.$iJob.'/'.$sFile)) {
			throw new MiJobException('File doesn\'t exist');
		}

		$oFile = fopen(FILES_DIR.'/'.$iJob.'/'.$sFile, 'r');
		if (!$oFile) {
			throw new MiJobException('Failed to open file');
		}
		
		header('Content-Type: application/x-unknown');
		header('Content-Disposition: attachment; filename="'.$sFile.'";');
		while (!feof($oFile)) {
			$mBuffer = fread($oFile, 4096);
			print $mBuffer;
		}
		fclose($oFile);
		exit();
	}
}
?>
